home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-07-20 | 27.1 KB | 1,147 lines | [TEXT/MPCC] |
- //unit WASTE4;
-
- // { WASTE PROJECT: }
- // { Unit Four: Editing }
-
- // { Copyright © 1993-1994 Marco Piovanelli }
- // { All Rights Reserved }
- // C conversion by Dan Crevier
-
- #include "WASTEIntf.h"
-
- OSErr _WEInsertRun(long runIndex, long offset, long styleIndex, WEPtr pWE)
- {
- // { Insert a new element in the style run array, at the specified runIndex position. }
- // { The new element consists of the pair <offset, styleIndex>. }
-
- RunArrayElement element;
- OSErr err;
-
- // _WEInsertRun = noErr;
-
- // { prepare the element record to be inserted in the array }
- element.runStart = offset;
- element.styleIndex = styleIndex;
-
- // { do the insertion }
- err = _WEInsertSlot((Handle)pWE->hRuns, (Ptr)&element, runIndex + 1, sizeof(element));
- if (err != noErr)
- {
- return err;
- }
-
- // { increment style run count }
- pWE->nRuns = pWE->nRuns + 1;
-
- // { increment the reference count field of the style table element }
- // { referenced by the newly inserted style run }
- (*pWE->hStyles)[styleIndex].refCount = (*pWE->hStyles)[styleIndex].refCount + 1;
-
- return noErr;
- }
-
- OSErr _WERemoveRun(long runIndex, WEPtr pWE)
- {
- // { remove the specified element from the style run array }
- long styleIndex;
- OSErr err;
-
- styleIndex = (*pWE->hRuns)[runIndex].styleIndex;
-
- // { do the removal (errors returned by _WERemoveSlot can be safely ignored) }
- err = _WERemoveSlot((Handle)pWE->hRuns, runIndex, sizeof(RunArrayElement));
-
- // { decrement style run count }
- pWE->nRuns = pWE->nRuns - 1;
-
- // { decrement the reference count field of the style table element }
- // { that was referenced by the style run we have just removed }
- (*pWE->hStyles)[styleIndex].refCount = (*pWE->hStyles)[styleIndex].refCount - 1;
-
- return err;
- }
-
- void _WEChangeRun(long runIndex, long newStyleIndex, WEPtr pWE)
- {
- // { change the styleIndex field of the specified element of the style run array }
-
- long oldStyleIndex;
-
- // { do the change }
- oldStyleIndex = (*pWE->hRuns)[runIndex].styleIndex;
- (*pWE->hRuns)[runIndex].styleIndex = newStyleIndex;
-
- // { decrement the reference count field of the old style table element }
- (*pWE->hStyles)[oldStyleIndex].refCount = (*pWE->hStyles)[oldStyleIndex].refCount - 1;
-
- // { increment the reference count field of the new style table element }
- (*pWE->hStyles)[newStyleIndex].refCount = (*pWE->hStyles)[newStyleIndex].refCount + 1;
- }
-
- OSErr _WENewStyle(WERunAttributes *ts, long *styleIndex, WEPtr pWE)
- {
- // { given the specified WERunAttributes record, find the corresponding entry }
- // { in the style table (create a new entry if necessary), and return its index }
-
- StyleTablePtr pTable;
- StyleTableElement element;
- long index, unusedIndex;
- OSErr err;
-
- // _WENewStyle = noErr;
- pTable = *pWE->hStyles;
-
- // { see if the given style already exists in the style table }
- // { while scanning the table, also remember the position of the first unused style, if any }
- index = 0;
- unusedIndex = -1;
- while (index < pWE->nStyles)
- {
- // { perform a bitwise comparison between the current element and the specified style }
- if (_WEBlockCmp((Ptr)&pTable[index].info, (Ptr)ts, sizeof(WERunAttributes)))
- {
- *styleIndex = index; // { found: style already present }
- return noErr;
- }
-
- // { check for entries which aren't referenced and can be recycled }
- if (pTable[index].refCount == 0)
- {
- unusedIndex = index;
- }
- index = index + 1;
- } // { while }
-
- // { the specified style doesn't exist in the style table }
- // { see if we can recycle an unused entry }
- if (unusedIndex >= 0)
- {
- index = unusedIndex;
- pTable[index].info = *ts;
- }
- else
- {
- // { no reusable entry: we have to append a new element to the table }
- element.refCount = 0;
- element.info = *ts;
- err = _WEInsertSlot((Handle)pWE->hStyles, (Ptr)&element, index, sizeof(element));
- if (err != noErr)
- {
- return err;
- }
-
- // { update style count in the WE record }
- pWE->nStyles = index + 1;
- }
-
- // { return the index to the new element }
- *styleIndex = index;
-
- return noErr;
- }
-
- OSErr _WERedraw(long rangeStart, long rangeEnd, WEHandle hWE)
- {
- // { the WE record is guaranteed to be already locked }
- WEPtr pWE;
- LineArrayPtr pLines;
- long startLine, endLine;
- long oldTextHeight, newTextHeight;
- LongRect r;
- Rect viewRect, updateRect;
- RgnHandle saveClip;
- GrafPtr savePort;
- OSErr err;
-
- pWE = *hWE;
-
- // { do nothing if recalculation has been inhibited }
- if (!BTST(pWE->flags, weFInhibitRecal))
- {
- // { hide the caret }
- if (BTST(pWE->flags, weFCaretVisible))
- {
- _WEDrawCaret(hWE);
- }
-
- // { remember total text height }
- oldTextHeight = pWE->destRect.bottom - pWE->destRect.top;
-
- // { find line range affected by modification }
- startLine = _WEOffsetToLine(rangeStart, hWE);
- endLine = _WEOffsetToLine(rangeEnd, hWE);
-
- // { recalculate line breaks starting from startLine }
- err = _WERecalBreaks(&startLine, &endLine, hWE);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { recalculate slops }
- _WERecalSlops(startLine, endLine, hWE);
-
- // { calculate new total text height }
- newTextHeight = pWE->destRect.bottom - pWE->destRect.top;
-
- // { calculate the rectangle to redraw (in long coordinates) }
- r.left = -SHRT_MAX;
- r.right = SHRT_MAX;
- pLines = *pWE->hLines;
- r.top = pLines[startLine].lineOrigin;
-
- // { if total text height hasn't changed, it's enough to redraw lines up to endLine }
- // { otherwise we must redraw all lines from startLine on }
- if ((newTextHeight == oldTextHeight) && (endLine < pWE->nLines - 1))
- {
- r.bottom = pLines[endLine + 1].lineOrigin;
- }
- else if (newTextHeight < oldTextHeight)
- {
- r.bottom = oldTextHeight;
- }
- else
- {
- r.bottom = newTextHeight;
- }
-
- WEOffsetLongRect(&r, 0, pWE->destRect.top);
-
- // { calculate the intersection between this rectangle and the view rectangle }
- WELongRectToRect(&r, &updateRect);
- WELongRectToRect(&pWE->viewRect, &viewRect);
-
- if (SectRect(&updateRect, &viewRect, &updateRect))
- {
- // { set up the port and the clip region }
- GetPort(&savePort);
- SetPort(pWE->port);
-
- // { set the clip region to updateRect }
- saveClip = NewRgn();
- GetClip(saveClip);
- ClipRect(&updateRect);
-
- // { we only really need to redraw the visible lines }
- startLine = _WEPixelToLine(updateRect.top - pWE->destRect.top, hWE);
- endLine = _WEPixelToLine(updateRect.bottom - pWE->destRect.top - 1, hWE);
-
- // { redraw the lines (pass TRUE in the doErase parameter) }
- _WEDrawLines(startLine, endLine, true, hWE);
-
- // { erase the portion of the update rectangle below the last line (if any) }
- pLines = *pWE->hLines;
- updateRect.top = pWE->destRect.top + pLines[endLine + 1].lineOrigin;
- if (updateRect.top < updateRect.bottom)
- {
- EraseRect(&updateRect);
- }
-
- // { restore the clip region }
- SetClip(saveClip);
- DisposeRgn(saveClip);
-
- // { restore the port }
- SetPort(savePort);
-
- // { redraw the caret or the selection range }
- if (pWE->selStart < pWE->selEnd)
- {
- _WEHiliteRange(pWE->selStart, pWE->selEnd, hWE);
- }
- else
- {
- _WEDrawCaret(hWE);
- }
- } // { if SectRect }
-
- // { scroll the selection range into view }
- WESelView(hWE);
- } // { if recal not inhibited }
-
- // { clear result code }
- err = noErr;
-
- cleanup:
- // { return result code }
- return err;
- }
-
- OSErr _WESetStyleRange(long rangeStart, long rangeEnd, short mode, WETextStyle *ts, WEHandle hWE)
- {
- // { alter the style attributes of the specified text range according to ts and mode }
- // { the WE record is guaranteed to be already locked }
-
- WEPtr pWE;
- RunArrayHandle hRuns;
- long offset;
- long runIndex;
- long oldStyleIndex, newStyleIndex;
- WERunInfo runInfo;
- short temp;
- char continuousStyles;
- OSErr err;
-
- pWE = *hWE;
- hRuns = pWE->hRuns;
-
- // { if mode contains weDoToggleFace, we need to determine which QuickDraw styles }
- // { are continuous over the specified text range: those styles must be turned off }
- if (BTST(mode, kModeToggleFace))
- {
- temp = weDoFace;
- _WEContinuousStyleRange(rangeStart, rangeEnd, &temp, &runInfo.runAttrs.runStyle, hWE);
- continuousStyles = runInfo.runAttrs.runStyle.tsFace;
- }
- else
- {
- continuousStyles = 0;
- }
-
- // { find the index to the first style run in the specified range }
- offset = rangeStart;
- runIndex = _WEOffsetToRun(offset, hWE);
-
- // { run thru all the style runs that encompass the selection range }
- do
- {
- // { find style index for this run and retrieve corresponding style attributes }
- oldStyleIndex = (*hRuns)[runIndex].styleIndex;
- _WEGetIndStyle(runIndex, &runInfo, hWE);
-
- // { _WEGetIndStyle returns textLength + 1 in runInfo.runEnd for the last style run: }
- // { correct this anomaly (which is useful for other purposes, anyway) }
- if (runInfo.runEnd > pWE->textLength)
- {
- runInfo.runEnd = pWE->textLength;
- }
-
- // { apply changes to existing style attributes as requested }
- _WECopyStyle(ts, &runInfo.runAttrs.runStyle, continuousStyles, mode);
-
- // { recalculate font metrics, if necessary }
- if ((mode & (weDoFont + weDoSize + weDoFace + weDoAddSize)) != 0)
- {
- _WEFillFontInfo(pWE->port, &runInfo.runAttrs);
- }
-
- // { get a style index for the new attributes }
- err = _WENewStyle(&runInfo.runAttrs, &newStyleIndex, pWE);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { if offset falls on a style boundary and this style run has become identical }
- // { to the previous one, merge the two runs together }
- if ((offset == runInfo.runStart) && (runIndex > 0) &&
- ((*hRuns)[runIndex - 1].styleIndex == newStyleIndex))
- {
- err = _WERemoveRun(runIndex, pWE);
- if (err != noErr)
- {
- goto cleanup;
- }
- runIndex = runIndex - 1;
- }
-
- // { style index changed? }
- if (oldStyleIndex != newStyleIndex)
- {
- // { if offset is in the middle of a style run, insert a new style run in the run array }
- if (offset > runInfo.runStart)
- {
- err = _WEInsertRun(runIndex, offset, newStyleIndex, pWE);
- if (err != noErr)
- {
- goto cleanup;
- }
- runIndex = runIndex + 1;
- }
- else
- {
- // { otherwise just change the styleIndex field of the current style run element }
- _WEChangeRun(runIndex, newStyleIndex, pWE);
- }
-
- // { if specified range ends in the middle of a style run, insert yet another element }
- if (rangeEnd < runInfo.runEnd)
- {
- err = _WEInsertRun(runIndex, rangeEnd, oldStyleIndex, pWE);
- if (err != noErr)
- {
- goto cleanup;
- }
- }
- } // { if oldStyle != newStyle }
-
- // { go to next style run }
- runIndex = runIndex + 1;
- offset = runInfo.runEnd;
-
- } while (offset < rangeEnd);
-
- // { if the last style run ends exactly at the end of the specified range, }
- // { see if we can merge it with the following style run }
- if ((offset == rangeEnd) && (runIndex < pWE->nRuns) &&
- ((*hRuns)[runIndex].styleIndex == newStyleIndex))
- {
- err = _WERemoveRun(runIndex, pWE);
- if (err != noErr)
- {
- goto cleanup;
- }
- }
-
- // { clear result code }
- err = noErr;
-
- cleanup:
- // { return result code }
- return err;
- }
-
- OSErr _WEApplyStyleScrap(long rangeStart, long rangeEnd, WEStyleScrapHandle styleScrap, WEHandle hWE)
- {
- // { apply the given style scrap to the specified text range }
- // { the WE record is guaranteed to be already locked }
-
- WEPtr pWE;
- WEStyleScrapPeek pElement;
- long runStart, runEnd;
- short index, lastElement;
- WETextStyle ts;
- OSErr err;
-
- // _WEApplyStyleScrap = noErr;
- pWE = *hWE;
-
- // { loop through each element of the style scrap }
- lastElement = (*styleScrap)->scrpNStyles - 1;
- for(index = 0; index<=lastElement; index++)
- {
- // { get a pointer to the current scrap element }
- pElement = (WEStyleScrapPeek)&(*styleScrap)->scrpStyleTab[index];
-
- // { calculate text run to which this element is to be applied }
- runStart = rangeStart + pElement->first.scrpStartChar;
- if (index < lastElement)
- {
- runEnd = rangeStart + pElement->second.scrpStartChar;
- }
- else
- {
- runEnd = rangeEnd;
- }
-
- // { perform some range checking }
- if (runEnd > rangeEnd)
- {
- runEnd = rangeEnd;
- }
- if (runStart >= runEnd)
- {
- continue;
- }
-
- // { copy style to a local variable in case memory moves }
- ts = pElement->first.scrpAttrs.runStyle;
-
- // { apply the specified style to the range }
- err = _WESetStyleRange(runStart, runEnd, weDoAll + weDoReplaceFace, &ts, hWE);
- if (err != noErr)
- {
- return err;
- }
- }
- return noErr;
- }
-
- void _WEBumpRunStart(long runIndex, long deltaRunStart, WEPtr pWE)
- {
- // { add deltaLineStart to the lineStart field of all line records }
- // { starting from lineIndex }
-
- long *pStart;
- long nRuns;
-
- pStart = &(*pWE->hRuns)[runIndex].runStart;
- nRuns = pWE->nRuns;
-
- // { loop through the style run array adjusting the runStart fields }
- while (runIndex <= nRuns)
- {
- *pStart = *pStart + deltaRunStart;
- pStart = (long *)((long)(pStart) + sizeof(RunArrayElement));
- runIndex = runIndex + 1;
- }
- }
-
- OSErr _WERemoveRunRange(long rangeStart, long rangeEnd, WEHandle hWE)
- {
- // { the range of text between rangeStart and rangeEnd is being deleted }
- // { update the style run array (and the style table) accordingly }
- // { the WE handle must be locked on entry }
-
- WEPtr pWE;
- RunArrayPeek pRuns;
- long startRun, endRun;
- OSErr err;
-
- pWE = *hWE;
-
- // { find the index to the first and last style runs in the specified range }
- startRun = _WEOffsetToRun(rangeStart, hWE);
- endRun = _WEOffsetToRun(rangeEnd, hWE) - 1;
-
- // { remove all style runs between startRun and endRun }
- while (endRun > startRun)
- {
- err = _WERemoveRun(endRun, pWE);
- if (err != noErr)
- {
- goto cleanup;
- }
- endRun = endRun - 1;
- }
-
- // { move back all subsequent style runs }
- _WEBumpRunStart(startRun + 1, rangeStart - rangeEnd, pWE);
-
- if ((endRun == startRun) && (endRun < pWE->nRuns - 1))
- {
- pRuns = (RunArrayPeek)&(*pWE->hRuns)[endRun];
- pRuns->second.runStart = rangeStart;
- }
-
- // { remove the first style run if is has become zero length }
- pRuns = (RunArrayPeek)&(*pWE->hRuns)[startRun];
- if (pRuns->first.runStart == pRuns->second.runStart)
- {
- err = _WERemoveRun(startRun, pWE);
- if (err != noErr)
- {
- goto cleanup;
- }
- startRun = startRun - 1;
- }
-
- // { merge the first and last runs if they have the same style index }
- if (startRun >= 0)
- {
- pRuns = (RunArrayPeek)&(*pWE->hRuns)[startRun];
- if (pRuns->first.styleIndex == pRuns->second.styleIndex)
- {
- err = _WERemoveRun(startRun + 1, pWE);
- if (err != noErr)
- {
- goto cleanup;
- }
- }
- }
- // { clear result code }
- err = noErr;
-
- cleanup:
- // { return result code }
- return err;
- }
-
- void _WEBumpLineStart(long lineIndex, long deltaLineStart, WEPtr pWE)
- {
- // { add deltaLineStart to the lineStart field of all line records }
- // { starting from lineIndex }
-
- long *pStart;
- long nLines;
-
- pStart = &(*pWE->hLines)[lineIndex].lineStart;
- nLines = pWE->nLines;
-
- // { loop through the line array adjusting the lineStart fields }
- while (lineIndex <= nLines)
- {
- *pStart = *pStart + deltaLineStart;
- pStart = (long *)((long)pStart + sizeof(LineRec));
- lineIndex = lineIndex + 1;
- }
- }
-
- OSErr _WERemoveLineRange(long rangeStart, long rangeEnd, WEHandle hWE)
- {
- // { the range of text between rangeStart and rangeEnd is being deleted }
- // { update the line array accordingly }
- // { the WE handle must be locked on entry }
-
- WEPtr pWE;
- long startLine, endLine;
- OSErr err;
-
- // _WERemoveLineRange = noErr;
- pWE = *hWE;
-
- // { remove all line records between rangeStart and rangeEnd }
- startLine = _WEOffsetToLine(rangeStart, hWE) + 1;
- endLine = _WEOffsetToLine(rangeEnd, hWE);
- while (endLine >= startLine)
- {
- err = _WERemoveLine(endLine, pWE);
- if (err != noErr)
- {
- return err;
- }
- endLine = endLine - 1;
- } // { while }
-
- // { update the lineStart field of all the line records that follow }
- _WEBumpLineStart(startLine, rangeStart - rangeEnd, pWE);
-
- return noErr;
- }
-
- OSErr _WEDeleteRange(long rangeStart, long rangeEnd, WEHandle hWE)
- {
- // { used internally to delete a text range }
- // { if saveNullStyle is TRUE, the first style in the range is saved in nullStyle }
- // { the WE record is guaranteed to be already locked }
-
- WEPtr pWE;
- WERunInfo runInfo;
- long oldTextLength, newTextLength;
- long pText;
- OSErr err;
-
- pWE = *hWE;
-
- // { do nothing if the specified range is empty }
- if (rangeStart == rangeEnd)
- {
- goto cleanup1;
- }
-
- // { save the first style in the specified range in nullStyle }
- WEGetRunInfo(rangeStart, &runInfo, hWE);
- pWE->nullStyle = runInfo.runAttrs;
- BSET(pWE->flags, weFUseNullStyle);
-
- // { remove all line records between rangeStart and rangeEnd }
- err = _WERemoveLineRange(rangeStart, rangeEnd, hWE);
- if (err != noErr)
- {
- goto cleanup2;
- }
-
- // { remove all style runs between rangeStart and rangeEnd }
- err = _WERemoveRunRange(rangeStart, rangeEnd, hWE);
- if (err != noErr)
- {
- goto cleanup2;
- }
-
- // { calculate old and new text length }
- oldTextLength = pWE->textLength;
- newTextLength = oldTextLength - (rangeEnd - rangeStart);
-
- // { move the end of the text backwards over the old selection range }
- pText = (long)(*pWE->hText);
- BlockMoveData((Ptr)pText + rangeEnd, (Ptr)pText + rangeStart, oldTextLength - rangeEnd);
-
- // { compact the text handle }
- SetHandleSize((Handle)pWE->hText, newTextLength);
- err = MemError();
- if (err != noErr)
- {
- goto cleanup2;
- }
-
- // { update textLength field }
- pWE->textLength = newTextLength;
-
- cleanup1:
- // { clear result code }
- err = noErr;
-
- cleanup2:
- // { return result code }
- return err;
- }
-
- OSErr _WEInsertText(long offset, Ptr textPtr, long textLength, WEHandle hWE)
- {
- // { this routine assumes that the WE record is already locked }
-
- WEPtr pWE;
- long oldTextLength, newTextLength;
- long pInsPoint;
- OSErr err;
-
- pWE = *hWE;
-
- // { do nothing if textLength is zero or negative }
- if (textLength <= 0)
- {
- goto cleanup1;
- }
-
- // { calculate old and new length of text handle }
- oldTextLength = pWE->textLength;
- newTextLength = oldTextLength + textLength;
-
- // { leng the raw text handle }
- SetHandleSize((Handle)pWE->hText, newTextLength);
- err = MemError();
- if (err != noErr)
- {
- goto cleanup2;
- }
-
- // { calculate ptr to insertion point }
- pInsPoint = (long)(*pWE->hText) + offset;
-
- // { make room for the new text }
- BlockMoveData((Ptr)pInsPoint, (Ptr)(pInsPoint + textLength), oldTextLength - offset);
-
- // { insert new text at the insertion point }
- BlockMoveData(textPtr, (Ptr)pInsPoint, textLength);
-
- // { update the lineStart fields of all lines following the insertion point }
- _WEBumpLineStart(_WEOffsetToLine(offset, hWE) + 1, textLength, pWE);
-
- // { update the runStart fields of all style runs following the insertion point }
- _WEBumpRunStart(_WEOffsetToRun(offset - 1, hWE) + 1, textLength, pWE);
-
- // { update various fields in the WE record }
- pWE->textLength = newTextLength;
-
- // { if there is a valid null style, apply it to the newly inserted text }
- if (BTST(pWE->flags, weFUseNullStyle))
- {
- err = _WESetStyleRange(offset, offset + textLength, weDoAll + weDoReplaceFace, &pWE->nullStyle.runStyle, hWE);
- if (err != noErr)
- {
- goto cleanup2;
- }
- }
-
- cleanup1:
- // { clear result code }
- err = noErr;
-
- cleanup2:
- // { return result code }
- return err;
- }
-
- pascal OSErr WEDelete(WEHandle hWE)
- {
- WEPtr pWE;
- long offset;
- // WERunInfo runInfo;
- Boolean saveWELock;
- OSErr err;
-
- // WEDelete = noErr;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
- offset = pWE->selStart;
-
- // { do nothing if the selection range is empty }
- if (offset < pWE->selEnd)
- {
- // { delete the selection range }
- err = _WEDeleteRange(offset, pWE->selEnd, hWE);
- if (err != noErr)
- {
- return err;
- }
-
- // { selEnd becomes equal to selStart }
- pWE->selEnd = offset;
-
- // { redraw the text }
- err = _WERedraw(offset, offset, hWE);
- if (err != noErr)
- {
- return err;
- }
- } // { if non-empty selection }
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
-
- return noErr;
- }
-
- pascal OSErr WEInsert(Ptr textPtr, long textLength, WEStyleScrapHandle styleScrap, WEHandle hWE)
- {
- WEPtr pWE;
- long offset, endOffset;
- Boolean saveWELock;
- OSErr err;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
- offset = pWE->selStart;
-
- // { delete current selection }
- err = _WEDeleteRange(offset, pWE->selEnd, hWE);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { insert the new text at the insertion point }
- err = _WEInsertText(offset, textPtr, textLength, hWE);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { move the insertion point at the end of the inserted text }
- endOffset = offset + textLength;
- pWE->selStart = endOffset;
- pWE->selEnd = endOffset;
-
- if (styleScrap != nil)
- {
- // { if a styleScrap was supplied, apply it to the newly inserted text }
- err = _WEApplyStyleScrap(offset, endOffset, styleScrap, hWE);
- if (err != noErr)
- {
- goto cleanup;
- }
- }
-
- // { invalid the null style }
- BCLR(pWE->flags, weFUseNullStyle);
-
- // { redraw the text }
- err = _WERedraw(offset, endOffset, hWE);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { clear result code }
- err = noErr;
-
- cleanup:
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
-
- // { return result code }
- return err;
- }
-
- void _WEInsertByte(char theByte, WEHandle hWE)
- {
- WEPtr pWE;
- short db;
- long charLength;
- short byteType;
- short saveFont;
- GrafPtr savePort;
-
- pWE = *hWE;
- charLength = 1; // { assume 1-byte character by default }
- db = theByte << 8;
-
- // { delete current selection, if any }
- _WEDeleteRange(pWE->selStart, pWE->selEnd, hWE);
- pWE->selEnd = pWE->selStart;
-
- // { make sure the font script is synchronized with the keyboard script }
- _WESynchNullStyle(hWE);
-
- if (BTST(pWE->flags, weFDoubleByte))
- {
- // { special processing for double-byte characters }
- if (pWE->firstByte != 0)
- {
- // { if this byte is the second half of a double-byte character, }
- // { insert the two bytes at the same time (flush the double-byte cache) }
- db = pWE->firstByte << 8 + theByte;
- charLength = 2;
- pWE->firstByte = 0;
- }
- else
- {
- // { determine the byte-type of theByte; first set up the port and its font }
- GetPort(&savePort);
- SetPort(pWE->port);
- saveFont = pWE->port->txFont;
- TextFont(pWE->nullStyle.runStyle.tsFont);
-
- // { call CharByte }
- byteType = CharByte(&theByte, 0);
-
- // { put back font and port }
- TextFont(saveFont);
- SetPort(savePort);
-
- // { if theByte is the first half of a double-byte character, just cache it and exit }
- if (byteType == smFirstByte)
- {
- pWE->firstByte = theByte;
- return;
- }
- }
- } // { if double-byte script installed }
-
- // { insert the new character into the text }
- WEInsert((char *)&db, charLength, nil, hWE);
- }
-
- void _WEBackspace(WEHandle hWE)
- {
- // { this routine is called by WEKey to handle the backspace key }
- // { the WE record is guaranteed to be already locked }
-
- WEPtr pWE;
- long offset, charLength;
- OSErr err;
-
- pWE = *hWE;
- offset = pWE->selStart;
-
- // { if the selection range is not empty, delete the current selection range }
- if (offset < pWE->selEnd)
- {
- err = _WEDeleteRange(offset, pWE->selEnd, hWE);
- }
- else
- {
- // { do nothing if insertion point is at the beginning of the text }
- if (offset <= 0)
- {
- return;
- }
-
- // { determine the byte-type of the character preceding the insertion point }
- if (WECharByte(offset - 1, hWE) == smSingleByte)
- {
- charLength = 1;
- }
- else
- {
- charLength = 2;
- }
-
- // { delete the character }
- offset = offset - charLength;
- err = _WEDeleteRange(offset, offset + charLength, hWE);
- }
-
- // { keep track of current selection range }
- pWE->selStart = offset;
- pWE->selEnd = offset;
-
- // { redraw the text }
- err = _WERedraw(offset, offset, hWE);
- }
-
- pascal void WEKey(short key, short modifiers, WEHandle hWE)
- {
- WEPtr pWE;
- Boolean saveWELock;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { hide the caret if it's showing }
- if (BTST(pWE->flags, weFCaretVisible))
- {
- _WEDrawCaret(hWE);
- }
-
- // { hide the cursor (it will show again as soon as it's moved) }
- ObscureCursor();
-
- // { dispatch on key class (arrow keys, printable characters, backspace) }
- if ((key >= kArrowLeft) && (key <= kArrowDown))
- {
- _WEDoArrowKey(key, modifiers, hWE);
- }
- else if (key == kBackspace)
- {
- _WEBackspace(hWE);
- }
- else
- {
- _WEInsertByte(key, hWE);
- }
-
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
- }
-
- pascal OSErr WECut(WEHandle hWE)
- {
- OSErr err;
-
- // WECut = noErr;
-
- // { Cut is just Copy + Delete }
- err = WECopy(hWE);
- if (err != noErr)
- {
- return err;
- }
-
- err = WEDelete(hWE);
- if (err != noErr)
- {
- return err;
- }
- return noErr;
- }
-
- pascal OSErr WESetStyle(short mode, WETextStyle *ts, WEHandle hWE)
- {
- WEPtr pWE;
- ScriptCode fontScript;
- Boolean saveWELock;
- OSErr err;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { if the selection range is empty, set the null style }
- if (pWE->selStart == pWE->selEnd)
- {
- // { first make sure the nullStyle field contains valid information }
- _WESynchNullStyle(hWE);
-
- // { apply style changes to the nullStyle record }
- _WECopyStyle(ts, &pWE->nullStyle.runStyle, pWE->nullStyle.runStyle.tsFace, mode);
-
- // { if the font was altered, synchronize the keyboard script }
- if (BTST(pWE->flags, weFNonRoman))
- {
- if (BTST(mode, kModeFont))
- {
- fontScript = Font2Script(pWE->nullStyle.runStyle.tsFont);
- if (fontScript != GetEnvirons(smKeyScript))
- {
- KeyScript(fontScript);
- }
- }
- }
- }
- else
- {
- // { otherwise set the style of the selection range }
- err = _WESetStyleRange(pWE->selStart, pWE->selEnd, mode, ts, hWE);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { and redraw the text }
- err = _WERedraw(pWE->selStart, pWE->selEnd, hWE);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- }
-
- // { clear the result code }
- err = noErr;
-
- cleanup:
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
-
- // { return result code }
- return err;
- }
-
- pascal OSErr WEUseStyleScrap(WEStyleScrapHandle styleScrap, WEHandle hWE)
- {
- WEPtr pWE;
- Boolean saveWELock;
- OSErr err;
-
- // { lock the WE record }
- saveWELock = _WESetHandleLock((Handle)hWE, true);
- pWE = *hWE;
-
- // { apply the style scrap to the selection range }
- err = _WEApplyStyleScrap(pWE->selStart, pWE->selEnd, styleScrap, hWE);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { redraw the text }
- err = _WERedraw(pWE->selStart, pWE->selEnd, hWE);
-
- cleanup:
- // { unlock the WE record }
- _WESetHandleLock((Handle)hWE, saveWELock);
-
- // { return result code }
- return err;
- }
-
- pascal OSErr WEPaste(WEHandle hWE)
- {
- Handle hText, hStyles;
- long scrapResult, scrapOffset;
- OSErr err;
-
- hText = nil;
- hStyles = nil;
-
- // { allocate a handle to hold the text }
- err = _WEAllocate(0, kAllocTemp, (Handle *)&hText);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { look for a 'TEXT' item }
- scrapResult = GetScrap(hText, kTypeText, &scrapOffset);
- if (scrapResult <= 0)
- {
- err = scrapResult;
- goto cleanup;
- }
-
- // { allocate a handle to hold the style scrap }
- err = _WEAllocate(0, kAllocTemp, (Handle *)&hStyles);
- if (err != noErr)
- {
- goto cleanup;
- }
-
- // { look for a 'styl' item accompanying the text }
- scrapResult = GetScrap(hStyles, kTypeStyles, &scrapOffset);
-
- // { forget the handle if nothing was found or an error occurred }
- if (scrapResult <= 0)
- {
- _WEForgetHandle((Handle *)&hStyles);
- }
-
- // { lock down the text }
- HLock(hText);
-
- // { insert the text }
- err = WEInsert(*hText, GetHandleSize(hText), (WEStyleScrapHandle)hStyles, hWE);
-
- cleanup:
- // { clean up }
- _WEForgetHandle((Handle *)&hText);
- _WEForgetHandle((Handle *)&hStyles);
-
- // { return result code }
- return err;
- }
-